package dse.modules;

import java.util.Hashtable;

import dse.Cluster;
import dse.DataObject;
import dse.Network;
import dse.Node;

/**
 * This module is responsible for determining which node in a cluster is 
 * responsible for hosting a share of a data object.  
 * 
 * This is also used to map a data object to a single node in the network (for 
 * the DHT algorithm) USING cluster.  Even though the DHT algorithm does not use
 * or need clusters, we want the location that data objects are stored at to be
 * similar between the DHT and Mixed algorithms.  To this end, both algorithms 
 * first hash the data object to the same cluster, but the DHT takes it a step 
 * further and then hashes it to a single node in the cluster. Looking up a 
 * data object in the DHT algorithm uses the same idea.  
 * 
 * This can obviously not lead to an exact match between hosts in the two 
 * algorithms, but should be pretty close.
 * 
 * @author Sam
 */
public interface Assigner extends Module {
	/**
	 * This should use a hashing technique to assign the object to a cluster in
	 * the network.
	 * 
	 * @param dataObject	The object to assign.
	 * @param clusters		The clusters.
	 * @param maxClusterId	The maximum clutser id (for hashing).
	 * 
	 * @return	The clusters that should host the data object.  Note that this
	 * 			could potentially be empty in some cases, but should not contain
	 * 			duplicates.	
	 */
	Iterable<Cluster> assign (
			DataObject dataObject,
			Iterable<Cluster> clusters,
			int maxClusterId
			);
	
	/**
	 * This should use a hashing technique to assign the object to a node in
	 * the network.
	 * 
	 * @param dataObject	The object to assign.
	 * @param network		The network.	
	 * 
	 * @return	The node that should host the data object.  Note that this could
	 *  		potentially be null in some cases.	
	 */
	public Iterable<Node> assign (
			DataObject dataObject,
			Network network
			);
	/**
	 * This should use a hashing technique to assign the object to a node of the
	 * cluster.
	 * 
	 * @param dataObject	The object to assign.
	 * @param cluster
	 * 
	 * @return	
	 */
	Node assign (
			DataObject dataObject,
			Cluster cluster 
			);
	/**
	 * This should use a hashing technique to assign the object to a node of the
	 * cluster.
	 * 
	 * @param dataObject	The object to assign.
	 * @param shareIndex	The share to assign (starts at 1).
	 * @param cluster
	 * 
	 * @return	The node that should host the share.  Note that this could
	 *  		potentially be null in some cases.	
	 */
	Node assign (
			DataObject dataObject,
			int shareIndex,
			Cluster cluster 
			);
	/**
	 * This should hash the data object shares to appropriate nodes and host
	 * them on those nodes.  If enough valid nodes are found then the cluster's
	 * hosted data object list should be updated and this should return true.
	 * If there are not enough valid share hosts, then this should return false.
	 * 
	 * @param cluster
	 * @param dataObject
	 * @return				Whether or not the operation succeeded.
	 */
	boolean hostShares (Cluster cluster, DataObject dataObject);
	Hashtable<Node, Integer> hostedShares (Cluster cluster, DataObject dataObject);
	
	/**
	 * This should use a hashing technique to assign the object to a node of the
	 * network without clusters.
	 * 
	 * @param dataObject	The object to assign.
	 * @param shareIndex	The share to assign (starts at 1).
	 * @param network		The network
	 * @return	The node that should host the share.  Note that this could
	 *  		potentially be null in some cases.	
	 */
	public Node assign (DataObject dataObject, 
			int shareIndex, 
			Network network);
	
	/**
	 * This should hash the data object shares to appropriate nodes and host
	 * them on those nodes.  If enough valid nodes are found then the cluster's
	 * hosted data object list should be updated and this should return true.
	 * If there are not enough valid share hosts, then this should return false.
	 * 
	 * @param network
	 * @param dataObject
	 * @return				Whether or not the operation succeeded.
	 */
	public boolean hostShares (Network network, DataObject dataObject);
	//Get really hosted share and nodes
	public Hashtable<Node, Integer> hostedShares(Network network, DataObject dataObject);
}
